using System;
using System.Collections.Generic;
using OracleInternal.Common;

namespace OracleInternal.Sharding
{
	internal class ShardingRangeMap
	{
		private ShardRoutingCache m_shardRoutingCache;

		private RangeMap<OracleShardingKeyImpl, RangeMap<long, Chunk>> hashRangeMap = new RangeMap<OracleShardingKeyImpl, RangeMap<long, Chunk>>();

		private RangeMap<long, Chunk> defaultHashRangeMap = new RangeMap<long, Chunk>();

		private RangeMap<OracleShardingKeyImpl, RangeMap<OracleShardingKeyImpl, Chunk>> rangeMap = new RangeMap<OracleShardingKeyImpl, RangeMap<OracleShardingKeyImpl, Chunk>>();

		private RangeMap<OracleShardingKeyImpl, Chunk> defaultRangeMap = new RangeMap<OracleShardingKeyImpl, Chunk>();

		internal ShardingRangeMap(ShardRoutingCache shardRoutingCache)
		{
			m_shardRoutingCache = shardRoutingCache;
		}

		internal void Put(RoutingKey routingKey, Chunk chunk)
		{
			if (routingKey.ShardingKeys is HashRangeShardingKeys)
			{
				HashRangeShardingKeys hashRangeShardingKeys = routingKey.ShardingKeys as HashRangeShardingKeys;
				if (routingKey.SuperShardingKeys == null)
				{
					defaultHashRangeMap.Put(hashRangeShardingKeys.KeyLow.ShardKeyOraHash, hashRangeShardingKeys.KeyHigh.ShardKeyOraHash, chunk);
					return;
				}
				foreach (Tuple<OracleShardingKeyImpl, OracleShardingKeyImpl> key in routingKey.SuperShardingKeys.Keys)
				{
					List<RangeMap<long, Chunk>> list = hashRangeMap.Get(key.Item1, key.Item2);
					if (list == null || list.Count == 0)
					{
						RangeMap<long, Chunk> rangeMap = new RangeMap<long, Chunk>();
						rangeMap.Put(hashRangeShardingKeys.KeyLow.ShardKeyOraHash, hashRangeShardingKeys.KeyHigh.ShardKeyOraHash, chunk);
						hashRangeMap.Put(key.Item1, key.Item2, rangeMap);
					}
					else
					{
						list[0].Put(hashRangeShardingKeys.KeyLow.ShardKeyOraHash, hashRangeShardingKeys.KeyHigh.ShardKeyOraHash, chunk);
					}
				}
				return;
			}
			if (routingKey.SuperShardingKeys == null)
			{
				foreach (Tuple<OracleShardingKeyImpl, OracleShardingKeyImpl> key2 in routingKey.ShardingKeys.Keys)
				{
					defaultRangeMap.Put(key2.Item1, key2.Item2, chunk);
				}
				return;
			}
			throw new NotImplementedException();
		}

		internal List<Chunk> Get(OracleShardingKeyImpl superShardingKey, OracleShardingKeyImpl shardingKey)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)288, OracleTraceClassName.ShardingRangeMap, OracleTraceFuncName.Get);
			}
			long num = 0L;
			try
			{
				if (superShardingKey == null)
				{
					if (defaultRangeMap.Count == 0)
					{
						num = m_shardRoutingCache.GetShardKeyOraHash(shardingKey);
						return defaultHashRangeMap.Get(num);
					}
					if (defaultHashRangeMap.Count == 0)
					{
						return defaultRangeMap.Get(shardingKey);
					}
					num = m_shardRoutingCache.GetShardKeyOraHash(shardingKey);
					List<Chunk> collection = defaultHashRangeMap.Get(num);
					List<Chunk> collection2 = defaultRangeMap.Get(shardingKey);
					List<Chunk> list = new List<Chunk>();
					list.AddRange(collection);
					list.AddRange(collection2);
					return list;
				}
				List<RangeMap<long, Chunk>> list2 = null;
				List<RangeMap<OracleShardingKeyImpl, Chunk>> list3 = null;
				if (rangeMap.Count == 0)
				{
					list2 = hashRangeMap.Get(superShardingKey);
					if (list2 == null || list2.Count == 0)
					{
						return null;
					}
					num = m_shardRoutingCache.GetShardKeyOraHash(shardingKey);
					return list2[0].Get(num);
				}
				if (hashRangeMap.Count == 0)
				{
					list3 = rangeMap.Get(superShardingKey);
					if (list3 == null || list3.Count == 0)
					{
						return null;
					}
					return list3[0].Get(shardingKey);
				}
				List<Chunk> list4 = null;
				list2 = hashRangeMap.Get(superShardingKey);
				if (list2 == null || list2.Count == 0)
				{
					list4 = new List<Chunk>();
				}
				else
				{
					num = m_shardRoutingCache.GetShardKeyOraHash(shardingKey);
					list4 = list2[0].Get(num);
				}
				List<Chunk> list5 = null;
				list3 = rangeMap.Get(superShardingKey);
				list5 = ((list3 != null && list3.Count != 0) ? list3[0].Get(shardingKey) : new List<Chunk>());
				List<Chunk> list6 = new List<Chunk>();
				list6.AddRange(list4);
				list6.AddRange(list5);
				return list6;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, OracleTraceTag.Sharding, OracleTraceClassName.ShardingRangeMap, OracleTraceFuncName.Get, string.Format("Super Sharding Key = {0}, Sharding Key = {1}", (superShardingKey == null) ? "<none>" : superShardingKey.ToString(), shardingKey.ToString()));
				}
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)544, OracleTraceClassName.ShardingRangeMap, OracleTraceFuncName.Get);
				}
			}
		}

		internal List<Chunk> Get(RoutingKey routingKey)
		{
			if (routingKey.ShardingKeys is HashRangeShardingKeys)
			{
				HashRangeShardingKeys hashRangeShardingKeys = routingKey.ShardingKeys as HashRangeShardingKeys;
				if (routingKey.SuperShardingKeys == null)
				{
					return defaultHashRangeMap.Get(hashRangeShardingKeys.KeyLow.ShardKeyOraHash, hashRangeShardingKeys.KeyHigh.ShardKeyOraHash);
				}
				throw new NotImplementedException();
			}
			_ = routingKey.SuperShardingKeys;
			throw new NotImplementedException();
		}

		internal void Replace(RoutingKey routingKey, Chunk oldChunk, Chunk newChunk)
		{
			if (routingKey.ShardingKeys is HashRangeShardingKeys)
			{
				HashRangeShardingKeys hashRangeShardingKeys = routingKey.ShardingKeys as HashRangeShardingKeys;
				if (routingKey.SuperShardingKeys == null)
				{
					defaultHashRangeMap.Replace(hashRangeShardingKeys.KeyLow.ShardKeyOraHash, hashRangeShardingKeys.KeyHigh.ShardKeyOraHash, oldChunk, newChunk);
					return;
				}
				throw new NotImplementedException();
			}
			_ = routingKey.SuperShardingKeys;
			throw new NotImplementedException();
		}

		internal void Remove(RoutingKey routingKey, Chunk chunk)
		{
			if (routingKey.ShardingKeys is HashRangeShardingKeys)
			{
				HashRangeShardingKeys hashRangeShardingKeys = routingKey.ShardingKeys as HashRangeShardingKeys;
				if (routingKey.SuperShardingKeys == null)
				{
					defaultHashRangeMap.Remove(hashRangeShardingKeys.KeyLow.ShardKeyOraHash, hashRangeShardingKeys.KeyHigh.ShardKeyOraHash, chunk);
					return;
				}
				foreach (Tuple<OracleShardingKeyImpl, OracleShardingKeyImpl> key in routingKey.SuperShardingKeys.Keys)
				{
					List<RangeMap<long, Chunk>> list = hashRangeMap.Get(key.Item1, key.Item2);
					if (list != null && 0 < list.Count)
					{
						list[0].Remove(hashRangeShardingKeys.KeyLow.ShardKeyOraHash, hashRangeShardingKeys.KeyHigh.ShardKeyOraHash, chunk);
					}
				}
				return;
			}
			if (routingKey.SuperShardingKeys == null)
			{
				foreach (Tuple<OracleShardingKeyImpl, OracleShardingKeyImpl> key2 in routingKey.ShardingKeys.Keys)
				{
					defaultRangeMap.Remove(key2.Item1, key2.Item2, chunk);
				}
				return;
			}
			throw new NotImplementedException();
		}

		internal void Clear()
		{
			hashRangeMap.Clear();
			defaultHashRangeMap.Clear();
			rangeMap.Clear();
			defaultRangeMap.Clear();
		}
	}
}
